package values

import (
	"encoding/json"
	"errors"
	"fmt"
	"html/template"
	"math"
	"strconv"
	"strings"
	"time"

	"github.com/spf13/cast"
)

// String 转换目标为字符串, 如果转换失败, 则返回空字符串
func ToString(v any) string {
	if v == nil {
		return ""
	}
	to, _ := ToStringE(v)
	return to
}

// ToStringD 转换目标为字符串, 如果转换失败, 则返回defaultVal指定的默认值
func ToStringD(v any, defaultVal string) string {
	if v == nil {
		return defaultVal
	}
	if to, err := ToStringE(v); err == nil {
		return to
	}
	return defaultVal
}

// ToStringE  转换目标为字符串, 如果转换失败, 则返回空字符串和错误信息
func ToStringE(v any) (string, error) {
	if v == nil {
		return "", errors.New("ToStringE: nil pointer not support")
	}
	v, err := _anyToBaseParseV[string](v)
	if err != nil {
		return "", err
	}
	switch vs := v.(type) {
	case nil, struct{}, *struct{}:
		return "", nil
	case string:
		return vs, nil
	case bool:
		if vs {
			return "true", nil
		}
		return "false", nil
	case float64:
		return strconv.FormatFloat(vs, 'f', -1, 64), nil
	case float32:
		return strconv.FormatFloat(float64(vs), 'f', -1, 32), nil
	case int:
		return strconv.Itoa(vs), nil
	case int64:
		return strconv.FormatInt(vs, 10), nil
	case int32:
		return strconv.Itoa(int(vs)), nil
	case int16:
		return strconv.FormatInt(int64(vs), 10), nil
	case int8:
		return strconv.FormatInt(int64(vs), 10), nil
	case uint:
		return strconv.FormatUint(uint64(vs), 10), nil
	case uint64:
		return strconv.FormatUint(uint64(vs), 10), nil
	case uint32:
		return strconv.FormatUint(uint64(vs), 10), nil
	case uint16:
		return strconv.FormatUint(uint64(vs), 10), nil
	case uint8:
		return strconv.FormatUint(uint64(vs), 10), nil
	case json.Number:
		return vs.String(), nil
	case []byte:
		return BytesToString(vs), nil
	case template.HTML:
		return string(vs), nil
	case template.URL:
		return string(vs), nil
	case template.JS:
		return string(vs), nil
	case template.CSS:
		return string(vs), nil
	case template.HTMLAttr:
		return string(vs), nil
	case fmt.Stringer:
		return vs.String(), nil
	case error:
		return vs.Error(), nil
	case complex64:
		return fmt.Sprintf("(%g+%gi)", real(vs), imag(vs)), nil
	case complex128:
		return fmt.Sprintf("(%g+%gi)", real(vs), imag(vs)), nil
	default:
		if s, err := json.Marshal(vs); err == nil {
			return BytesToString(s), nil
		}
		return "", fmt.Errorf("ToStringE: unable to %#v of type %T to string", vs, vs)
	}
}

// StringToInt string 转为 int , 如果转换失败, 则返回零值
func StringToInt(v string) int {
	to, _ := StringToIntE(v)
	return to
}

// StringToIntD string 转为 int , 如果转换失败, 则返回指定默认值
func StringToIntD(v string, defautVal int) int {
	if to, err := StringToIntE(v); err == nil {
		return to
	}
	return defautVal
}

// StringToIntE string 转为 int , 如果转换失败, 则返回零值和错误信息
func StringToIntE(v string) (int, error) {
	if v == "" {
		return 0, errors.New("StringToIntX: unable to empty string to int")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		to, err := strconv.ParseInt(strings.Split(vs, ".")[0], 0, 0)
		if err == nil {
			if to > math.MaxInt || to < math.MinInt {
				return 0, errors.New("StringToIntX: int overflow")
			}
			return int(to), nil
		}
	}
	return 0, fmt.Errorf("StringToIntX: unable to %v of type string to int", v)
}

// StringToInt8 string 转为 int8 , 如果转换失败, 则返回零值
func StringToInt8(v string) int8 {
	to, _ := StringToInt8E(v)
	return to
}

// StringToInt8D string 转为 int8 , 如果转换失败, 则返回指定默认值
func StringToInt8D(v string, defautVal int8) int8 {
	if to, err := StringToInt8E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToInt8E string 转为 int8 , 如果转换失败, 则返回零值和错误信息
func StringToInt8E(v string) (int8, error) {
	if v == "" {
		return 0, errors.New("StringToIntX: unable to empty string to int8")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		to, err := strconv.ParseInt(strings.Split(vs, ".")[0], 0, 0)
		if err == nil {
			if to > math.MaxInt8 || to < math.MinInt8 {
				return 0, errors.New("StringToIntX: int8 overflow")
			}
			return int8(to), nil
		}
	}
	return 0, fmt.Errorf("StringToIntX: unable to %v of type string to int8", v)
}

// StringToInt16 string 转为 int16 , 如果转换失败, 则返回零值
func StringToInt16(v string) int16 {
	to, _ := StringToInt16E(v)
	return to
}

// StringToInt16D string 转为 int16 , 如果转换失败, 则返回指定默认值
func StringToInt16D(v string, defautVal int16) int16 {
	if to, err := StringToInt16E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToInt16E string 转为 int16 , 如果转换失败, 则返回零值和错误信息
func StringToInt16E(v string) (int16, error) {
	if v == "" {
		return 0, errors.New("StringToIntX: unable to empty string to int16")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		to, err := strconv.ParseInt(strings.Split(vs, ".")[0], 0, 0)
		if err == nil {
			if to > math.MaxInt16 || to < math.MinInt16 {
				return 0, errors.New("StringToIntX: int16 overflow")
			}
			return int16(to), nil
		}
	}
	return 0, fmt.Errorf("StringToIntX: unable to %v of type string to int16", v)
}

// StringToInt32 string 转为 int32 , 如果转换失败, 则返回零值
func StringToInt32(v string) int32 {
	to, _ := StringToInt32E(v)
	return to
}

// StringToInt32D string 转为 int32 , 如果转换失败, 则返回指定默认值
func StringToInt32D(v string, defautVal int32) int32 {
	if to, err := StringToInt32E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToInt32E string 转为 int32 , 如果转换失败, 则返回零值和错误信息
func StringToInt32E(v string) (int32, error) {
	if v == "" {
		return 0, errors.New("StringToIntX: unable to empty string to int32")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		to, err := strconv.ParseInt(strings.Split(vs, ".")[0], 0, 0)
		if err == nil {
			if to > math.MaxInt32 || to < math.MinInt32 {
				return 0, errors.New("StringToIntX: int32 overflow")
			}
			return int32(to), nil
		}
	}
	return 0, fmt.Errorf("StringToIntX: unable to %v of type string to int32", v)
}

// StringToInt64 string 转为 int64 , 如果转换失败, 则返回零值
func StringToInt64(v string) int64 {
	to, _ := StringToInt64E(v)
	return to
}

// StringToInt64D string 转为 int64 , 如果转换失败, 则返回指定默认值
func StringToInt64D(v string, defautVal int64) int64 {
	if to, err := StringToInt64E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToInt64E string 转为 int64 , 如果转换失败, 则返回零值和错误信息
func StringToInt64E(v string) (int64, error) {
	if v == "" {
		return 0, errors.New("StringToIntX: unable to empty string to int64")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		to, err := strconv.ParseInt(strings.Split(vs, ".")[0], 0, 0)
		if err == nil {
			return to, nil
		} else {
			return 0, errors.New("StringToIntX: int64 overflow")
		}
	}
	return 0, fmt.Errorf("StringToIntX: unable to %v of type string to int64", v)
}

// StringToUint string 转为 uint , 如果转换失败, 则返回零值
func StringToUint(v string) uint {
	to, _ := StringToUintE(v)
	return to
}

// StringToUintD string 转为 uint , 如果转换失败, 则返回指定默认值
func StringToUintD(v string, defautVal uint) uint {
	if to, err := StringToUintE(v); err == nil {
		return to
	}
	return defautVal
}

// StringToUintE string 转为 uint , 如果转换失败, 则返回零值和错误信息
func StringToUintE(v string) (uint, error) {
	if v == "" {
		return 0, errors.New("StringToUintX: unable to empty string to uint")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		if vs[0] == '-' {
			return 0, errors.New("StringToUintX: negative \"-xxx\" to uint not support")
		}
		to, err := strconv.ParseUint(strings.Split(vs, ".")[0], 0, 0)
		if err == nil && to <= math.MaxUint {
			return uint(to), nil
		}
		return 0, errors.New("StringToUintX: uint overflow")
	}
	return 0, fmt.Errorf("StringToUintX: unable to %v of type string to uint", v)
}

// StringToUint8 string 转为 uint8 , 如果转换失败, 则返回零值
func StringToUint8(v string) uint8 {
	to, _ := StringToUint8E(v)
	return to
}

// StringToUint8D string 转为 uint8 , 如果转换失败, 则返回指定默认值
func StringToUint8D(v string, defautVal uint8) uint8 {
	if to, err := StringToUint8E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToUint8E string 转为 uint8 , 如果转换失败, 则返回零值和错误信息
func StringToUint8E(v string) (uint8, error) {
	if v == "" {
		return 0, errors.New("StringToUintX: unable to empty string to uint8")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		if vs[0] == '-' {
			return 0, errors.New("StringToUintX: negative \"-xxx\" to uint not support")
		}
		to, err := strconv.ParseUint(strings.Split(vs, ".")[0], 0, 0)
		if err == nil && to <= math.MaxUint8 {
			return uint8(to), nil
		}
		return 0, errors.New("StringToUintX: uint8 overflow")
	}
	return 0, fmt.Errorf("StringToUintX: unable to %v of type string to uint8", v)
}

// StringToUint16 string 转为 uint16 , 如果转换失败, 则返回零值
func StringToUint16(v string) uint16 {
	to, _ := StringToUint16E(v)
	return to
}

// StringToUint16D string 转为 uint16 , 如果转换失败, 则返回指定默认值
func StringToUint16D(v string, defautVal uint16) uint16 {
	if to, err := StringToUint16E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToUint16E string 转为 uint16 , 如果转换失败, 则返回零值和错误信息
func StringToUint16E(v string) (uint16, error) {
	if v == "" {
		return 0, errors.New("StringToUintX: unable to empty string to uint16")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		if vs[0] == '-' {
			return 0, errors.New("StringToUintX: negative \"-xxx\" to uint not support")
		}
		to, err := strconv.ParseUint(strings.Split(vs, ".")[0], 0, 0)
		if err == nil && to <= math.MaxUint16 {
			return uint16(to), nil
		}
		return 0, errors.New("StringToUintX: uint16 overflow")
	}
	return 0, fmt.Errorf("StringToUintX: unable to %v of type string to uint16", v)
}

// StringToUint32 string 转为 uint32 , 如果转换失败, 则返回零值
func StringToUint32(v string) uint32 {
	to, _ := StringToUint32E(v)
	return to
}

// StringToUint32D string 转为 uint32 , 如果转换失败, 则返回指定默认值
func StringToUint32D(v string, defautVal uint32) uint32 {
	if to, err := StringToUint32E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToUint32E string 转为 uint32 , 如果转换失败, 则返回零值和错误信息
func StringToUint32E(v string) (uint32, error) {
	if v == "" {
		return 0, errors.New("StringToUintX: unable to empty string to uint32")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		if vs[0] == '-' {
			return 0, errors.New("StringToUintX: negative \"-xxx\" to uint not support")
		}
		to, err := strconv.ParseUint(strings.Split(vs, ".")[0], 0, 0)
		if err == nil && to <= math.MaxUint32 {
			return uint32(to), nil
		}
		return 0, errors.New("StringToUintX: uint32 overflow")
	}
	return 0, fmt.Errorf("StringToUintX: unable to %v of type string to uint32", v)
}

// StringToUint64 string 转为 uint64 , 如果转换失败, 则返回零值
func StringToUint64(v string) uint64 {
	to, _ := StringToUint64E(v)
	return to
}

// StringToUint64D string 转为 uint64 , 如果转换失败, 则返回指定默认值
func StringToUint64D(v string, defautVal uint64) uint64 {
	if to, err := StringToUint64E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToUint64E string 转为 uint64 , 如果转换失败, 则返回零值和错误信息
func StringToUint64E(v string) (uint64, error) {
	if v == "" {
		return 0, errors.New("StringToUintX: unable to empty string to uint64")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		if vs[0] == '-' {
			return 0, errors.New("StringToUintX: negative \"-xxx\" to uint not support")
		}
		to, err := strconv.ParseUint(strings.Split(vs, ".")[0], 0, 0)
		if err == nil {
			return to, nil
		} else {
			return 0, errors.New("StringToUintX: uint64 overflow")
		}
	}
	return 0, fmt.Errorf("StringToUintX: unable to %v of type string to uint64", v)
}

// StringToUint64 string 转为 bool , 如果转换失败, 则返回零值
func StringToBool(v string) bool {
	to, _ := StringToBoolE(v)
	return to
}

// StringToUint64D string 转为 bool , 如果转换失败, 则返回指定默认值
func StringToBoolD(v string, defautVal bool) bool {
	if to, err := StringToBoolE(v); err == nil {
		return to
	}
	return defautVal
}

// StringToUint64E string 转为 uint64 , 如果转换失败, 则返回零值和错误信息
func StringToBoolE(v string) (bool, error) {
	if v == "" {
		//空字符串默认为false
		return false, nil
	}
	switch strings.ToLower(v) {
	case "true", "t", "1", "yes", "y", "on", "enable", "enabled", "checked":
		return true, nil
	case "false", "f", "0", "no", "n", "off", "disable", "disabled", "nil", "null", "undefined":
		return false, nil
	default:
		return false, fmt.Errorf("StringToBoolX: unable to %v of type string to bool", v)
	}
}

// StringToFloat32 string 转为 float32 , 如果转换失败, 则返回零值
func StringToFloat32(v string) float32 {
	to, _ := StringToFloat32E(v)
	return to
}

// StringToFloat32D string 转为 float32 , 如果转换失败, 则返回指定默认值
func StringToFloat32D(v string, defautVal float32) float32 {
	if to, err := StringToFloat32E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToFloat32E string 转为 float32 , 如果转换失败, 则返回零值和错误信息
func StringToFloat32E(v string) (float32, error) {
	if v == "" {
		return 0, errors.New("StringToFloatX: unable to empty string to float32")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		to, err := strconv.ParseFloat(vs, 32)
		if err == nil {
			return float32(to), nil
		}
		return 0, errors.New("StringToFloatX: value is too large to convert to float32")
	}
	return 0, fmt.Errorf("StringToFloatX: unable to %v of type string to float32", v)
}

// StringToFloat64 string 转为 float64 , 如果转换失败, 则返回零值
func StringToFloat64(v string) float64 {
	to, _ := StringToFloat64E(v)
	return to
}

// StringToFloat64D string 转为 float64 , 如果转换失败, 则返回指定默认值
func StringToFloat64D(v string, defautVal float64) float64 {
	if to, err := StringToFloat64E(v); err == nil {
		return to
	}
	return defautVal
}

// StringToFloat64E string 转为 float64 , 如果转换失败, 则返回零值和错误信息
func StringToFloat64E(v string) (float64, error) {
	if v == "" {
		return 0, errors.New("StringToFloatX: unable to empty string to float64")
	}
	if vs, ok := MatchNumberSNToDecimal(v); ok {
		to, err := strconv.ParseFloat(vs, 64)
		if err == nil {
			return to, nil
		}
		return 0, errors.New("StringToFloatX: value is too large to convert to float64")
	}
	return 0, fmt.Errorf("StringToFloatX: unable to %v of type string to float64", v)
}

// StringToTime string 转为 time.Time(UTC时区), 如果转换失败, 则返回零值
//   - 如日期时间字符串未包含时区信息时则使用UTC时区
func StringToTime(v string) time.Time {
	to, _ := StringToTimeWith(v, time.UTC)
	return to
}

// StringToTimeD string 转为 time.Time(UTC时区), 如果转换失败, 则返回指定默认值
//   - 如日期时间字符串未包含时区信息时则使用UTC时区
func StringToTimeD(v string, defautVal time.Time) time.Time {
	if to, err := StringToTimeWith(v, time.UTC); err == nil {
		return to
	}
	return defautVal
}

// StringToTimeE string 转为 time.Time(UTC时区), 如果转换失败, 则返回零值和错误信息
//   - 如日期时间字符串未包含时区信息时则使用UTC时区
func StringToTimeE(v string) (time.Time, error) {
	return StringToTimeWith(v, time.UTC)
}

// StringToTimeWith string 转为指定的时区的 time.Time(指定时区), 如果转换失败, 则返回零值和错误信息
//   - 如日期时间字符串未包含时区信息时则使用location指定的时区
func StringToTimeWith(v string, location *time.Location) (time.Time, error) {
	if v == "" {
		return time.Time{}, errors.New("StringToTimeWith: unable to empty string to time.Time")
	}
	if location == nil {
		return time.Time{}, errors.New("StringToTimeWith: location is nil")
	}
	if to, err := cast.StringToDateInDefaultLocation(v, location); err == nil {
		if to.Location() == location {
			return to, nil
		}
		return to.In(location), nil
	}
	return time.Time{}, fmt.Errorf("StringToTimeWith: unable to %s of type string to time.Time", v)
}

// StringToTimeDuration string 转为 time.Duration , 如果转换失败, 则返回零值
func StringToTimeDuration(v string) time.Duration {
	to, _ := StringToTimeDurationE(v)
	return to
}

// StringToTimeDurationD string 转为 time.Duration , 如果转换失败, 则返回指定默认值
func StringToTimeDurationD(v string, defautVal time.Duration) time.Duration {
	if to, err := StringToTimeDurationE(v); err == nil {
		return to
	}
	return defautVal
}

// StringToTimeDurationE string 转为 time.Duration , 如果转换失败, 则返回零值和错误信息
func StringToTimeDurationE(v string) (toVal time.Duration, err error) {
	if v == "" {
		return 0, errors.New("StringToTimeDurationX: unable to empty string to time.Duration")
	}
	if IsFloat(v) {
		v = strings.Split(v, ".")[0]
	}
	if IsInt(v) {
		toVal, err = time.ParseDuration(v + "ns")
		if err == nil {
			return toVal, nil
		}
		return 0, fmt.Errorf("StringToTimeDurationX: unable to %s of type string to time.Duration", v)
	}

	for _, c := range v {
		switch c {
		case 'n', 's', 'u', 'µ', 'm', 'h':
			continue
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			continue
		default:
			return 0, fmt.Errorf("StringToTimeDurationX: unable to %s of type string to time.Duration", v)
		}
	}
	toVal, err = time.ParseDuration(v)
	if err == nil {
		return toVal, nil
	}
	return 0, fmt.Errorf("StringToTimeDurationX: unable to %#v of type %T to time.Duration", v, v)
}

// StringToTimeMonth string 转为 time.Month , 如果转换失败, 则返回零值
func StringToTimeMonth(v string) time.Month {
	to, _ := StringToTimeMonthE(v)
	return to
}

// StringToTimeMonthD string 转为 time.Month , 如果转换失败, 则返回指定默认值
func StringToTimeMonthD(v string, defautVal time.Month) time.Month {
	if to, err := StringToTimeMonthE(v); err == nil {
		return to
	}
	return defautVal
}

// StringToTimeMonthE string 转为 time.Month , 如果转换失败, 则返回零值和错误信息
func StringToTimeMonthE(v string) (toVal time.Month, err error) {
	if v == "" {
		return toVal, errors.New("StringToTimeMonthX: unable to empty string to time.Month")
	}
	vs := strings.ToLower(v)
	switch vs {
	default:
		return toVal, fmt.Errorf("StringToTimeMonthX: unable to %s of type string to time.Month", v)
	case "january", "jan", "1", "1月", "一月":
		return time.January, nil
	case "february", "feb", "2", "2月", "二月":
		return time.February, nil
	case "march", "mar", "3", "3月", "三月":
		return time.March, nil
	case "april", "apr", "41", "4月", "四月":
		return time.April, nil
	case "may", "5", "5月", "五月":
		return time.May, nil
	case "june", "jun", "6", "6月", "六月":
		return time.June, nil
	case "july", "jul", "7", "7月", "七月":
		return time.July, nil
	case "august", "aug", "8", "8月", "八月":
		return time.August, nil
	case "september", "sep", "9", "9月", "九月":
		return time.September, nil
	case "october", "oct", "10", "10月", "十月":
		return time.October, nil
	case "november", "nov", "11", "11月", "十一月":
		return time.November, nil
	case "december", "dec", "12", "12月", "十二月":
		return time.December, nil
	}
}

// StringToTimeWeekday string 转为 time.Weekday , 如果转换失败, 则返回零值
func StringToTimeWeekday(v string) time.Weekday {
	to, _ := StringToTimeWeekdayE(v)
	return to
}

// StringToTimeWeekdayD string 转为 time.Weekday , 如果转换失败, 则返回指定默认值
func StringToTimeWeekdayD(v string, defautVal time.Weekday) time.Weekday {
	if to, err := StringToTimeWeekdayE(v); err == nil {
		return to
	}
	return defautVal
}

// StringToTimeWeekdayE string 转为 time.Weekday , 如果转换失败, 则返回零值和错误信息
func StringToTimeWeekdayE(v string) (toVal time.Weekday, err error) {
	if v == "" {
		return toVal, errors.New("StringToTimeWeekdayX: unable to empty string  to time.Weekday")
	}
	vs := strings.ToLower(v)
	switch vs {
	default:
		return toVal, fmt.Errorf("StringToTimeWeekdayX: unable to %s of type string to time.Weekday", v)
	case "sunday", "sun", "0", "周7", "周日", "星期日", "星期天":
		return time.Sunday, nil
	case "monday", "mon", "1", "周1", "周一", "星期一":
		return time.Monday, nil
	case "tuesday", "tue", "2", "周2", "周二", "星期二":
		return time.Tuesday, nil
	case "wednesday", "wed", "3", "周3", "周三", "星期三":
		return time.Wednesday, nil
	case "thursday", "thu", "4", "周4", "周四", "星期四":
		return time.Thursday, nil
	case "friday", "fri", "5", "周5", "周五", "星期五":
		return time.Friday, nil
	case "saturday", "sat", "6", "周6", "周六", "星期六":
		return time.Saturday, nil
	}
}

// StringToUnix string 转为 Unix时间戳(秒), 如果转换失败, 则返回零值
//   - 如待转换参数值为不含有时区的日期时间字符串，则使用UTC时区
func StringToUnix(v string) int64 {
	to, _ := StringToUnixWith(v, time.UTC)
	return to
}

// StringToUnixD string 转为 Unix时间戳(秒) , 如果转换失败, 则返回指定默认值
//   - 如待转换参数值为不含有时区的日期时间字符串，则使用UTC时区
func StringToUnixD(v string, defautVal int64) int64 {
	if to, err := StringToUnixWith(v, time.UTC); err == nil {
		return to
	}
	return defautVal
}

// StringToUnixE string 转为 Unix时间戳(秒) , 如果转换失败, 则返回零值和错误信息
//   - 如待转换参数值为不含有时区的日期时间字符串，则使用UTC时区
func StringToUnixE(v string) (toVal int64, err error) {
	return StringToUnixWith(v, time.UTC)
}

// StringToUnixWith string 转为 Unix时间戳(秒), 转换失败则返回0值和错误信息
//   - location 如待转换参数值为不含有时区的日期时间字符串，则使用location指定的时区
func StringToUnixWith(v string, location *time.Location) (int64, error) {
	if v == "" {
		return 0, errors.New("StringToUnixWith: unable empty string to unix seconds(int64)")
	}
	if location == nil {
		return 0, errors.New("StringToUnixWith: location is nil")
	}
	if IsFloat(v) {
		v = strings.Split(v, ".")[0]
	}
	// 整数字符串
	if IsUint(v) {
		v, err := strconv.ParseInt(v, 0, 0)
		if err == nil {
			return v, nil
		}
	}
	// 日期时间字符串
	if vs, e := cast.StringToDateInDefaultLocation(v, time.UTC); e == nil {
		return vs.Unix(), nil
	}
	return 0, fmt.Errorf("StringToUnixWith: unable to %s of type string to unix seconds(int64)", v)
}

// StringToUnixMilli string 转为 Unix时间戳(毫秒), 如果转换失败, 则返回零值
//   - 如待转换参数值为不含有时区的日期时间字符串，则使用UTC时区
func StringToUnixMilli(v string) int64 {
	to, _ := StringToUnixMilliWith(v, time.UTC)
	return to
}

// StringToUnixMilliD string 转为 Unix时间戳(毫秒) , 如果转换失败, 则返回指定默认值
//   - 如待转换参数值为不含有时区的日期时间字符串，则使用UTC时区
func StringToUnixMilliD(v string, defautVal int64) int64 {
	if to, err := StringToUnixMilliWith(v, time.UTC); err == nil {
		return to
	}
	return defautVal
}

// StringToUnixMilliE string 转为 Unix时间戳(毫秒) , 如果转换失败, 则返回零值和错误信息
//   - 如待转换参数值为不含有时区的日期时间字符串，则使用UTC时区
func StringToUnixMilliE(v string) (toVal int64, err error) {
	return StringToUnixMilliWith(v, time.UTC)
}

// StringToUnixMilliWith string 转为 Unix时间戳(毫秒), 转换失败则返回0值和错误信息
//   - location 如待转换参数值为不含有时区的日期时间字符串，则使用location指定的时区
func StringToUnixMilliWith(v string, location *time.Location) (int64, error) {
	if v == "" {
		return 0, errors.New("StringUnixMilliWith: unable to empty string to unix milliseconds(int64)")
	}
	if location == nil {
		return 0, errors.New("StringUnixMilliWith: location is nil")
	}
	if IsFloat(v) {
		v = strings.Split(v, ".")[0]
	}
	// 整数字符串
	if IsUint(v) {
		v, err := strconv.ParseInt(v, 0, 0)
		if err == nil {
			return v, nil
		}
	}
	// 日期时间字符串
	if vs, e := cast.StringToDateInDefaultLocation(v, time.UTC); e == nil {
		return vs.UnixMilli(), nil
	}
	return 0, fmt.Errorf("StringToUnixWith: unable to %s of type string to unix milliseconds(int64)", v)
}
